//
//  FLHttpCommunicate.m
//  faceLooker
//
//  Created by yww on 2018/12/28.
//  Copyright © 2018年 yww. All rights reserved.
//

#import "FLHttpCommunicate.h"

#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>
#define IOS_CELLULAR    @"pdp_ip0"
#define IOS_WIFI        @"en0"
#define IOS_VPN         @"utun0"
#define IP_ADDR_IPv4    @"ipv4"
#define IP_ADDR_IPv6    @"ipv6"
@interface FLHttpCommunicate (){
    AFHTTPSessionManager *_HTTPManager;
}

@end

@implementation FLHttpCommunicate
- (id)init{
    if (self = [super init]){
        _HTTPManager = [AFHTTPSessionManager manager];
        // 如果设置了false,那么发送的请求header中就不会自动加上cookie信息
        _HTTPManager.requestSerializer.HTTPShouldHandleCookies = YES;
        _HTTPManager.requestSerializer  = [AFHTTPRequestSerializer serializer];
        _HTTPManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        [_HTTPManager.requestSerializer setTimeoutInterval:TIME_NETOUT];
        //把版本号信息传导请求头中
        [_HTTPManager.requestSerializer setValue:[NSString stringWithFormat:@"iOS-%@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]] forHTTPHeaderField:@"MM-Version"];
        
        [_HTTPManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept" ];
        _HTTPManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json",@"text/html", @"text/plain",nil];
    }
    return self;
}

+ (id)sharedInstance{
    static FLHttpCommunicate * HTTPCommunicate;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        HTTPCommunicate = [[FLHttpCommunicate alloc] init];
    });
    return HTTPCommunicate;
}

#pragma mark - 枚举接口管理请求类
+ (void)createRequest:(HTTP_COMMAND_LIST)taskID
            WithParam:(NSDictionary *)param
           withMethod:(HTTPRequestMethod)method
              success:(void(^)(id result))success
              failure:(void(^)(NSError *erro))failure
              showHUD:(UIView *)showView{
    if (taskID < HTTP_METHOD_RESERVE){
        [[FLHttpCommunicate sharedInstance] createUnloginedRequest:taskID WithParam:param withMethod:method success:success failure:failure showHUD:showView];
    }
}


/**
 createUnlogined Request

 @param taskID 接口
 @param param 参数
 @param method 方法
 @param success 成功
 @param failure 失败
 @param showView 提示的view
 */
- (void)createUnloginedRequest:(HTTP_COMMAND_LIST)taskID WithParam:(NSDictionary *)param withMethod:(HTTPRequestMethod)method success:(void(^)(id result))success failure:(void(^)(NSError *erro))failure showHUD:(UIView *)showView{
    
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    //转菊花
    [MBProgressHUD wj_showActivityLoading:@"加载中...." toView:showView];
    //url地址
    NSString * url = [NSString stringWithUTF8String:LMHttpMethod[taskID]];
    NSString *URLString = [NSString stringWithFormat:@"%@%@",URL_BASE,url];
    
    //将cookie通过请求头的形式传到服务器，比较是否和服务器一致
    NSData *cookiesData = [[NSUserDefaults standardUserDefaults] objectForKey:@"Cookie"];
    if([cookiesData length]) {
        //拿到所有的cookies
        NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
        for (NSHTTPCookie *cookie in cookies) {
            //判断cookie是否等于服务器约定的ECM_ID
            if ([cookie.name isEqualToString:@"ECM_ID"]) {
                //实现了一个管理cookie的单例对象,每个cookie都是NSHTTPCookie类的实例,将cookies传给服务器
                [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
            }
        }
    }
    
    //请求
    NSMutableURLRequest *request = [_HTTPManager.requestSerializer requestWithMethod:[self getStringForRequestType:method] URLString:[[NSURL URLWithString:URLString relativeToURL:_HTTPManager.baseURL] absoluteString] parameters:param error:nil];
    
    //请求类 就算弃用了我也要用
    NSURLSessionDataTask *dataTask = [_HTTPManager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        //出现错误
        if (error) {
           if (showView) {//终止菊花
                [MBProgressHUD hideHUDForView:showView animated:YES ];
           }
            //提示
            UIWindow *window = [[UIApplication sharedApplication] keyWindow];
            if (error.code == -1009) {
                [MBProgressHUD showError:@"网络已断开" toView:window];
            }else if (error.code == -1005){
                [MBProgressHUD showError:@"网络连接已中断" toView:window];
            }else if(error.code == -1001){
                [MBProgressHUD showError:@"请求超时" toView:window];
            }else if (error.code == -1003){
                [MBProgressHUD showError:@"未能找到使用指定主机名的服务器" toView:window];
            }else{
                [MBProgressHUD showError:[NSString stringWithFormat:@"code:%d %@",error.code,error.localizedDescription] toView:window];
            }
            
            //设置系统网络连接菊花
            if (failure != nil){
                [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
                failure(error);
            }
        } else {//请求成功
            if (success != nil){
                //终止所有菊花
                [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
                if (showView) {
                    [MBProgressHUD hideHUDForView:showView animated:YES];
                }
                //获取服务器传的请求头cookie信息，并保存
                NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: [NSURL URLWithString:URL_BASE]];
                NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
                //保存cookie
                [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"Cookie"];
               
                //输出结果
                id result = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
                success(result);
            }
        }
    }];
    //恢复请求对话
    [dataTask resume];
}

#pragma mark - 文件上传和下载
//上传

/**
 请求

 @param taskID 接口
 @param param 参数
 @param Exparam 上传参数
 @param method 方法
 @param success 成功
 @param uploadFileProgress 进度
 @param failure 失败
 */
+ (void)createRequest:(HTTP_COMMAND_LIST)taskID
            WithParam:(NSDictionary*)param
          withExParam:(NSDictionary*)Exparam
           withMethod:(HTTPRequestMethod)method
              success:(void (^)(id result))success
   uploadFileProgress:(void(^)(NSProgress *uploadProgress))uploadFileProgress
              failure:(void (^)(NSError* erro))failure{
    if (taskID < HTTP_METHOD_RESERVE){
        [[FLHttpCommunicate sharedInstance] createUnloginedRequest:taskID WithParam:param withExParam:Exparam withMethod:method success:success failure:failure uploadFileProgress:uploadFileProgress];
    }
}

//创建
- (void)createUnloginedRequest:(HTTP_COMMAND_LIST)taskID WithParam:(NSDictionary *)param withExParam:(NSDictionary*)Exparam withMethod:(HTTPRequestMethod)method success:(void(^)(id result))success failure:(void(^)(NSError *erro))failure uploadFileProgress:(void(^)(NSProgress *uploadProgress))uploadFileProgress{
    //转联网菊花
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    //URL地址
    NSString * url = [NSString stringWithUTF8String:LMHttpMethod[taskID]];
    NSString *URLString = [NSString stringWithFormat:@"%@%@",URL_BASE,url];
    //将cookie通过请求头的形式传到服务器，比较是否和服务器一致
    NSData *cookiesData = [[NSUserDefaults standardUserDefaults] objectForKey:@"Cookie"];
    if([cookiesData length]) {
        //拿到所有的cookies
        NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
        for (NSHTTPCookie *cookie in cookies) {
            //判断cookie是否等于服务器约定的ECM_ID
            if ([cookie.name isEqualToString:@"ECM_ID"]) {
                //实现了一个管理cookie的单例对象,每个cookie都是NSHTTPCookie类的实例,将cookies传给服务器
                [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
            }
        }
    }
    
    //请求
    NSMutableURLRequest *request = [_HTTPManager.requestSerializer multipartFormRequestWithMethod:[self getStringForRequestType:method] URLString:URLString parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        //图片上传
        if (Exparam) {
            for (NSString *key in [Exparam allKeys]) {
                [formData appendPartWithFileData:[Exparam objectForKey:key] name:key fileName:[NSString stringWithFormat:@"%@.png",key] mimeType:@"image/jpeg"];
            }
        }
        
    } error:nil];
    //请求类
    NSURLSessionDataTask *dataTask = [_HTTPManager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
        if (uploadProgress) {
            //上传进度
            uploadFileProgress (uploadProgress);
        }
    } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
        if (downloadProgress) {
            //下载进度
        }
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error){
        if (error) {
            //错误提示
            UIWindow *window = [[UIApplication sharedApplication] keyWindow];
            if (error.code == -1009) {
                [MBProgressHUD showError:@"网络已断开" toView:window];
            }else if (error.code == -1005){
                [MBProgressHUD showError:@"网络连接已中断" toView:window];
            }else if(error.code == -1001){
                [MBProgressHUD showError:@"请求超时" toView:window];
            }else if (error.code == -1003){
                [MBProgressHUD showError:@"未能找到使用指定主机名的服务器" toView:window];
            }else{
                [MBProgressHUD showError:[NSString stringWithFormat:@"code:%ld %@",error.code,error.localizedDescription] toView:window];
            }
            //错误原因
            if (failure != nil){
                failure(error);
            }
        } else {
            if (success != nil){//请求成功
                [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
                
                //获取服务器传的请求头cookie信息，并保存
                NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: [NSURL URLWithString:URL_BASE]];
                NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
                //保存cookie
                [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"Cookie"];
                //返回结果
                id result = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
                success(result);
            }
        }
    }];
    
    [dataTask resume];
}


/**
 下载

 @param URLString 地址接口
 @param downloadFileProgress 进度
 @param setupFilePath 文件保存路径
 @param downloadCompletionHandler 回调
 */
+ (void)createDownloadFileWithURLString:(NSString *)URLString
                   downloadFileProgress:(void(^)(NSProgress *downloadProgress))downloadFileProgress
                          setupFilePath:(NSURL*(^)(NSURLResponse *response))setupFilePath
              downloadCompletionHandler:(void (^)(NSURL *filePath, NSError *error))downloadCompletionHandler{
    if (URLString) {
        [[FLHttpCommunicate sharedInstance]createUnloginedDownloadFileWithURLString:URLString downloadFileProgress:downloadFileProgress setupFilePath:setupFilePath downloadCompletionHandler:downloadCompletionHandler];
    }
}

- (void)createUnloginedDownloadFileWithURLString:(NSString *)URLString
                            downloadFileProgress:(void(^)(NSProgress *downloadProgress))downloadFileProgress
                                   setupFilePath:(NSURL*(^)(NSURLResponse *response))setupFilePath
                       downloadCompletionHandler:(void (^)(NSURL *filePath, NSError *error))downloadCompletionHandler{
    //请求
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString] cachePolicy:1 timeoutInterval:15];
    //请求对话
    NSURLSessionDownloadTask *dataTask = [_HTTPManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        //下载进度
        downloadFileProgress(downloadProgress);
        
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        //设置保存目录
        return setupFilePath(response);
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        //下载完成
        downloadCompletionHandler(filePath,error);
    }];
    [dataTask resume];
}

#pragma  mark 自定义协议 返回NSDictionary
+ (NSURLSessionTask *)GET:(NSString *)url
               parameters:(id)parameters
                dictBlock:(OptionDict)optionDict
               errorBlock:(OptionError)optionError{
    return [self GET:url parameters:parameters dictBlock:optionDict errorBlock:optionError indicatorVisible:YES];
}

+ (NSURLSessionTask *)GET:(NSString *)url
               parameters:(id)parameters
                dictBlock:(OptionDict)optionDict
               errorBlock:(OptionError)optionError
         indicatorVisible:(BOOL)visible{
    //设置联网数据菊花
    if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    
    //session管理
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];//增加格式
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    [manager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    /*
    //备用
    manager.requestSerializer = [AFJSONRequestSerializer serializer];//请求为application/json
    manager.responseSerializer = [AFJSONResponseSerializer serializer];//接收转为application/json
    [manager.requestSerializer setValue:@"text/html; charset=utf-8" forHTTPHeaderField:@"Content-Type"];//请求类型
    */
    
    
    /*
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    manager.securityPolicy = securityPolicy;
    //客户端验证
    [self sessionDidReceiveAuthentication:manager];
    */
    
    
    //请求操作
    NSURLSessionTask *operation = [manager GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        //下载进度
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //返回数据
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        if (optionError) optionError(error);//出现错误
    }];
    
    return operation;
}


+ (NSURLSessionTask *)POST:(NSString *)url
                parameters:(id)parameters
                 dictBlock:(OptionDict)optionDict
                errorBlock:(OptionError)optionError{
    return [self POST:url parameters:parameters dictBlock:optionDict errorBlock:optionError indicatorVisible:YES];
    
}


+ (NSURLSessionTask *)POST:(NSString *)url
                parameters:(id)parameters
                 dictBlock:(OptionDict)optionDict
                errorBlock:(OptionError)optionError
          indicatorVisible:(BOOL)visible{
    
    if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    //    manager.securityPolicy = securityPolicy;
    //客户端验证
    //    [self sessionDidReceiveAuthentication:manager];
    
    //保险性添加格式
    
    /*
     700
     hou_xin_60
     hou_wu_180
     Y_ji_70
     chezi_L_30+25_20
     50_cun+100_lic
     jia_meng 50
     */
    
    manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json",@"text/json",@"text/javascript",@"text/html",nil,nil];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    [manager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    //manager.requestSerializer = [AFJSONRequestSerializer serializer];//请求为application/json
    //manager.responseSerializer = [AFJSONResponseSerializer serializer];//接收转为application/json
    NSURLSessionTask *operation = [manager POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        //上传进度
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        if (optionDict) optionDict(dict);
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (optionError) optionError(error);
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    }];
    return operation;
}
#pragma  mark 自定义协议 返回NSData
+ (NSURLSessionTask *)POST:(NSString *)url
                parameters:(id)parameters
                   success:(OptionData)optionData
                     error:(OptionError)optionError {
    return [self POST:url parameters:parameters success:optionData error:optionError indicatorVisible:YES];
}
+ (NSURLSessionTask *)POST:(NSString *)url
                parameters:(id)parameters
                   success:(OptionData)optionData
                     error:(OptionError)optionError
          indicatorVisible:(BOOL)visible{
    
    if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
     AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    //    manager.securityPolicy = securityPolicy;
    //客户端验证
    //    [self sessionDidReceiveAuthentication:manager];
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];//将数据转化为NSData
    NSURLSessionTask *operation = [manager POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        //上传进度
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (optionData) optionData(responseObject);
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (optionError) optionError(error);
        if (visible) [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    }];
    return operation;
}

//客户端验证
+ (void)sessionDidReceiveAuthentication:(AFHTTPSessionManager *)manager{
    
    __weak __block AFHTTPSessionManager *sessionManager = manager;
    [sessionManager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *_credential) {
        
        // 获取服务器的trust object
        SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
        //导入自签名证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"fullchain" ofType:@"cer"];
        NSData   *caCert = [NSData dataWithContentsOfFile:cerPath];
        //        NSString *severCerPath = [[NSBundle mainBundle] pathForResource:@"smart.dreamp.tv" ofType:@"cer"];
        //        NSData* severCaCert = [NSData dataWithContentsOfFile:severCerPath];
        NSSet *cerArray = [[NSSet alloc]initWithObjects:caCert, nil];
        //        NSArray *cerArray = @[caCert];
        sessionManager.securityPolicy.pinnedCertificates = cerArray;
        SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
        NSCAssert(caRef != nil, @"caRef is nil");
        NSArray *caArray = @[(__bridge id)(caRef)];
        NSCAssert(caArray != nil, @"caArray is nil");
        OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
        SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
        NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
        //选择质询认证的处理方式
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __autoreleasing NSURLCredential *credential = nil;
        //NSURLAuthenticationMethodServerTrust质询认证方式
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            //基于客户端的安全策略来决定是否信任该服务器，不信任则不响应质询。
            if ([sessionManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                //创建质询证书
                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                //确认质询方式
                if (credential) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
            } else {
                //取消质询
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        } else {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        }
        
        return disposition;
    }];
}
#pragma  mark 自定义协议头 设置Header
+ (NSURLSessionTask *)GET:(NSString *)url
                   header:(NSDictionary *)headerDic
               parameters:(id)parameters
                  timeOut:(NSTimeInterval)timeOut
                dictBlock:(OptionDict)optionDict
               errorBlock:(OptionError)optionError{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //保险性添加格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    //    manager.securityPolicy = securityPolicy;
    //    [self sessionDidReceiveAuthentication:manager]; //客户端验证
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = timeOut>0?timeOut:TIME_NETOUT;
    if (headerDic) {
        for (NSString *key in [headerDic allKeys]) {
            [manager.requestSerializer setValue:headerDic[key] forHTTPHeaderField:key];
        }
    }
    
    NSURLSessionTask *operation = [manager GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        //下载进度
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (optionError) optionError(error);
    }];
    return operation;
}
+ (NSURLSessionTask *)POST:(NSString *)url
                    header:(NSDictionary *)headerDic
                parameters:(id)parameters
                   timeOut:(NSTimeInterval)timeOut
                 dictBlock:(OptionDict)optionDict
                errorBlock:(OptionError)optionError{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //保险性添加格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    /*
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
        manager.securityPolicy = securityPolicy;
        [self sessionDidReceiveAuthentication:manager]; //客户端验证
    */
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = timeOut>0?timeOut:TIME_NETOUT;
    if (headerDic) {
        for (NSString *key in [headerDic allKeys]) {
            [manager.requestSerializer setValue:headerDic[key] forHTTPHeaderField:key];
        }
    }
    
    NSURLSessionTask *operation = [manager POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        //上传进度
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (optionError) optionError(error);
    }];
    return operation;
}


+ (NSURLSessionTask *)PUT:(NSString *)url
                   header:(NSDictionary *)headerDic
               parameters:(id)parameters
                  timeOut:(NSTimeInterval)timeOut
                dictBlock:(OptionDict)optionDict
               errorBlock:(OptionError)optionError{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //保险性添加格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    //    manager.securityPolicy = securityPolicy;
    //    [self sessionDidReceiveAuthentication:manager]; //客户端验证
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = timeOut>0?timeOut:TIME_NETOUT;
    if (headerDic) {
        for (NSString *key in [headerDic allKeys]) {
            [manager.requestSerializer setValue:headerDic[key] forHTTPHeaderField:key];
        }
    }
    NSURLSessionTask *operation = [manager PUT:url parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //费用
        if (optionError) optionError(error);
    }];
    
    return operation;
}

//州
+ (NSURLSessionTask *)DELETE:(NSString *)url
                      header:(NSDictionary *)headerDic
                  parameters:(id)parameters
                     timeOut:(NSTimeInterval)timeOut
                   dictBlock:(OptionDict)optionDict
                  errorBlock:(OptionError)optionError{
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //保险性添加格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    //ca证书
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
    securityPolicy.validatesDomainName = NO;           //是否需要验证域名
    //    manager.securityPolicy = securityPolicy;
    //    [self sessionDidReceiveAuthentication:manager]; //客户端验证
    
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = timeOut>0?timeOut:TIME_NETOUT;
    if (headerDic) {
        for (NSString *key in [headerDic allKeys]) {
            [manager.requestSerializer setValue:headerDic[key] forHTTPHeaderField:key];
        }
    }
    NSURLSessionTask *operation = [manager DELETE:url parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (optionError) optionError(error);
    }];
    
    return operation;
}


+ (NSURLSessionTask *)POST:(NSString *)url
                   headers:(NSDictionary *)headerDic
                  fileData:(NSData*)data
                 imageType:(NSString *)imageType
                parameters:(id)parameters
                   timeOut:(NSTimeInterval)timeOut
                 dictBlock:(OptionDict)optionDict
                errorBlock:(OptionError)optionError{
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    //保险性添加格式
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
    /*
     //ca证书
     AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
     securityPolicy.allowInvalidCertificates = YES;      //是否允许使用自签名证书
     securityPolicy.validatesDomainName = NO;           //是否需要验证域名
     manager.securityPolicy = securityPolicy;
     [self sessionDidReceiveAuthentication:manager]; //客户端验证
     */
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    manager.requestSerializer.timeoutInterval = timeOut>0?timeOut:TIME_NETOUT;
    if (headerDic) {
        for (NSString *key in [headerDic allKeys]) {
            [manager.requestSerializer setValue:headerDic[key] forHTTPHeaderField:key];
        }
    }
    
    NSURLSessionDataTask *task = [manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        // 直接以 key value 的形式向 formData 中追加二进制数据
        [formData appendPartWithFileData:data name:@"myimage" fileName:imageType mimeType:@"image/jpeg"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        //进度
        NSLog(@"进度==%@",uploadProgress);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
        //NSDictionary *dict = (NSDictionary *)responseObject;
        if (optionDict) optionDict(dict);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        optionError(error);
    }];
    
    return task;
}

#pragma mark - 私有方法 GET Request type as string
-(NSString *)getStringForRequestType:(HTTPRequestMethod)type {
    NSString *requestTypeString;
    switch (type) {
        case POST:
            requestTypeString = @"POST";
            break;
            
        case GET:
            requestTypeString = @"GET";
            break;
            
        case PUT:
            requestTypeString = @"PUT";
            break;
            
        case DELETE:
            requestTypeString = @"DELETE";
            break;
            
        default:
            requestTypeString = @"POST";
            break;
    }
    
    return requestTypeString;
}

-(NSString*)DataTOjsonString:(id)object{
    NSString *jsonString = nil;
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object
                                                       options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                                                         error:&error];
    if (! jsonData) {
        NSLog(@"Got an error: %@", error);
    } else {
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    return jsonString;
}
#pragma mark - 获取ip地址
+ (NSString *)getIPAddress:(BOOL)preferIPv4{
    NSArray *searchArray = preferIPv4?
    @[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ]:@[ IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ];
    
    NSDictionary *addresses = [self getIPAddresses];
    NSLog(@"IP地址addresses: %@", addresses);
    __block NSString *address;
    [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop){
         address = addresses[key];
         //筛选出IP地址格式
         if([self isValidatIP:address]) *stop = YES;
     } ];
    return address ? address : @"0.0.0.0";
    
}
//判断是否是ip地址
+ (BOOL)isValidatIP:(NSString *)ipAddress {
    if (ipAddress.length == 0) {
        return NO;
    }
    NSString *urlRegEx = @"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlRegEx options:0 error:&error];
    
    if (regex != nil) {
        NSTextCheckingResult *firstMatch=[regex firstMatchInString:ipAddress options:0 range:NSMakeRange(0, [ipAddress length])];
        if (firstMatch) {
            NSRange resultRange = [firstMatch rangeAtIndex:0];
            NSString *result=[ipAddress substringWithRange:resultRange];
            
            //输出结果
            NSLog(@"%@",result);
            return YES;
        }
    }
    
    return NO;
}

//包括4g地址
+ (NSDictionary *)getIPAddresses{
    NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
    //当前的接口
    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces)) {
        // 循环遍历接口 //
        struct ifaddrs *interface;
        for(interface=interfaces; interface; interface=interface->ifa_next) {
            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
                continue;
            }
            
            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
            if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
                NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
                NSString *type;
                
               if(addr->sin_family == AF_INET){
                    if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv4;
                    }
                }else {
                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
                        type = IP_ADDR_IPv6;
                    }
                }
                
                
                if(type) {
                    NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
                    addresses[key] = [NSString stringWithUTF8String:addrBuf];
                }
            }
        }
        // 释放
        freeifaddrs(interfaces);
    }
    return [addresses count] ? addresses : nil;
}

@end
